/***************************************************************************//**
 * @file mac_TDMA.h
 * @brief for mac TDMA
 * @author ze .
 * @date  2022/7/03.
 * @copyright Copyright 
 ******************************************************************************/
#ifndef _MAC_TDMA_H_
#define _MAC_TDMA_H_

#include "stdint.h"
#include "stdio.h"

#define FILE_SLOT_NUM  30   //每2s有1个FILE槽，最大周期60s，共30个槽
#define FILE_SLOT_GROUP_NUM  5//一共5组SPVN槽，不会增加

#define SPVNED_DEVICE_MAX_CAPACITY  150 //具备心跳的设备最大数量，当前协议设计的数量为148个，ID1-ID148均支持心跳； 具备中继功能的节点 使用SystemId通信，系统全局使用相同序列信道，仅心跳/广播/文件时分传输窗口通道使用特殊信道
#define SPVN_TIME_DEFAULT   300//300 //考虑到时间同步精度，最大值300s，全局即所有设备的默认心跳时间 单位s，必须为10的整数倍！！由于SPVN_SLOT_GROUP_NUM槽组数量最大为24， 最小值20s；
#define SPVN_SLOT_NUM       (SPVN_TIME_DEFAULT / 2) //最大值为255 每2s有1个SPVN槽，最大周期300s，共150个槽，
#define SPVN_SLOT_GROUP_NUM (SPVNED_DEVICE_MAX_CAPACITY / SPVN_SLOT_NUM) //最大值为24组，24*6
#define SPVN_SLOT_GROUP_MAX_NUM  24 //系统支持的最大 心跳槽组的数量为24个
#define SPVN_WINDOW_WIDTH    984 //单位1/32768 暂定每个心跳窗口宽度在30ms //

typedef struct
{
  uint8_t  byGroupIdx;
  uint8_t  bySlotIdx;
  uint16_t wSpvnTime;
  uint32_t dwDeadline;
}SPVN_SLOT_CB_ST;

typedef struct 
{
    uint8_t bySeq;   
    uint8_t byMallocedId[SPVN_SLOT_NUM];//HUB端管理的该槽分配的Id情况，0表示该槽未被使用，0xFF表示该槽被多播/广播地址使用
}SPVN_SLOT_MAP_GROUP_ST;

typedef struct
{
    uint8_t byLen; // 该组文件传输槽的宽度
    uint8_t bySeq;    
    uint8_t byMallocedId[FILE_SLOT_NUM];//HUB端管理的该槽分配的Id情况，0表示该槽未被使用，0xFF表示该槽被多播/广播地址使用
}FILE_SLOT_MAP_GROUP_ST;

/***
 *@brief 全清0初始化心跳时间槽 
 *@param 
 *@param
 *@return int >0 maclloced idx； -1 failed
 * 
*/
int spvnSlotClearInit(void) ;

/***
 *@brief 分配心跳时间槽 ，共SPVN_SLOT_NUM150个槽 每个间隔2s，又分成SPVN_SLOT_SUB_GROUP_NUMBER15个子组，每子组SPVN_SLOT_SUB_GROUP_LENGTH10个槽长度即20s；
 *@param nodeId，提出申请的nodeId
 *@param SpvnTime， SpvnTime心跳周期 单位s
 *@return int >0 maclloced idx； -1 failed
 * 
*/
int spvnSlotMalloc(uint8_t nodeId, uint16_t SpvnTime) ;

/***
 *@brief 节点删除或修改心跳时间后 先释放原有心跳时间槽 
 *@param nodeId，需释放
 *@return int >0 maclloced idx； -1 failed
 * 
*/
int spvnSlotFree(uint8_t nodeId);

/***
 *@brief 节点删除或修改心跳时间后 先释放原有心跳时间槽  ( (u32)sysRtcCount >> 16)s % 150。则可算出当前所处的spvnSlotIdx
 *@param nodeId，表示分配给改Id的槽及未被分配的槽
 *@param slotGroupIdx，表示查找的组别
 *@param pMallocedIdxBitMask OUT出参 位域表示可用的心跳时间槽，该指针对象长度为 150bit/8 +1 = 19 bytes 
 *@param isIdleInclude 是否包含空闲的槽位
 *@return int >=0 Gruop idx； -1 failed
 * 
*/
int spvnSlotAvailableGet(uint8_t nodeId, uint8_t slotGroupIdx, uint8_t *pMallocedIdxBitMask, uint8_t isIdleInclude);
void spvnSlotPrintfAll();

void getNextSpvnDeadline(uint16_t* pOutSpvnTime ,uint32_t* pOutNextDeadline);
/***
 *@brief 检查当前时刻是否符合条件 ( (u32)sysRtcCount >> 16)s % 150。则可算出当前所处的spvnSlotIdx
 *@param destId 报文发送的目的地址，源地址为自身
 *@param transType 发送的类型，见枚举 TRANS_REQ_E
 *@return int >=0  sucess； -1 failed
 * 
*/
int checkChannelSlotAvailable(uint8_t destId,uint8_t transType);

//设置子设备心跳上报间隔、槽的位置等
void setSpvnSlot(uint8_t groupIdx, uint8_t slotIdx, uint16_t spvnTime);//SpvnTime 单位s
//心跳槽初始化
void spvnSlotInit(void);

#endif
